﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DatabaseDataSets.cs" company="SmartPlan">
//   SmartPlan 2011
// </copyright>
// <summary>
//   The db diff ds.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace DbDiff.Common.DataAccess
{
    using System;
    using System.Data;
    using System.Runtime.Serialization;

    /// <summary>
    /// The db diff ds.
    /// </summary>
    internal class DatabaseDataSets : DbObjectsDs
    {
        /// <summary>
        ///   The dv ds.
        /// </summary>
        private DataViewDs[] dataViews;

        #region Init & Dispose

        /// <summary>
        ///   Initializes a new instance of the <see cref = "DatabaseDataSets" /> class.
        /// </summary>
        public DatabaseDataSets()
        {
            this.Init();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DatabaseDataSets"/> class.
        /// </summary>
        /// <param name="si">
        /// The serialization info
        /// </param>
        /// <param name="sc">
        /// The serialzation context
        /// </param>
        public DatabaseDataSets(SerializationInfo si, StreamingContext sc) : base(si, sc)
        {
            this.Init();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DatabaseDataSets"/> class.
        /// </summary>
        /// <param name="datasetName">
        /// The dataset name.
        /// </param>
        public DatabaseDataSets(string datasetName)
        {
            this.DataSetName = datasetName;
            this.Init();
        }

        #region DtView enum

        /// <summary>
        /// The dt view.
        /// </summary>
        public enum DtView
        {
            /// <summary>
            ///   The check by table name.
            /// </summary>
            CheckByTableName = 0,

            /// <summary>
            ///   The check by key.
            /// </summary>
            CheckByKey,

            /// <summary>
            ///   The index by table name.
            /// </summary>
            IndexByTableName,

            /// <summary>
            ///   The primary key by table name.
            /// </summary>
            PrimaryKeyByTableName,

            /// <summary>
            ///   The unique by table name.
            /// </summary>
            UniqueByTableName,

            /// <summary>
            ///   The all index by table name.
            /// </summary>
            AllIndexByTableName,

            /// <summary>
            ///   The all index by key.
            /// </summary>
            AllIndexByKey,

            /// <summary>
            ///   The field by table name.
            /// </summary>
            FieldByTableName,

            /// <summary>
            ///   The field by key.
            /// </summary>
            FieldByKey,

            /// <summary>
            ///   The foreign by table name.
            /// </summary>
            ForeignByTableName,

            /// <summary>
            ///   The foreign by key.
            /// </summary>
            ForeignByKey,

            /// <summary>
            ///   The index key by table name.
            /// </summary>
            IndexKeyByTableName,

            /// <summary>
            ///   The foreign key by table name.
            /// </summary>
            ForeignKeyByTableName,

            /// <summary>
            ///   The index key by key.
            /// </summary>
            IndexKeyByKey,

            /// <summary>
            ///   The foreign key by key.
            /// </summary>
            ForeignKeyByKey,

            /// <summary>
            ///   The maximum.
            /// </summary>
            MAXIMUM
        }

        #endregion

        /// <summary>
        /// The get data view.
        /// </summary>
        /// <param name="viewIndexer">
        /// The view indexer.
        /// </param>
        /// <returns>
        /// The dataview
        /// </returns>
        /// <exception cref="Exception">
        /// </exception>
        public DataViewDs GetDataView(DtView viewIndexer)
        {
            if (viewIndexer == DtView.MAXIMUM)
            {
                throw new Exception("You can't use MAXIMUM!");
            }

            return this.dataViews[(int)viewIndexer];
        }

        #endregion Init & Dispose

        /// <summary>
        /// Return Foreign keys
        /// </summary>
        /// <param name="schema">
        /// The schema name
        /// </param>
        /// <param name="tableName">
        /// The table Name
        /// </param>
        /// <returns>
        /// The datarow view for the table 
        /// </returns>
        public DataRowView[] GetForeign(string schema, string tableName)
        {
            return this.dataViews[(int)DtView.ForeignByTableName].FindRows(new object[] { schema, tableName }, false);
        }

        /// <summary>
        /// The get foreign keys.
        /// </summary>
        /// <param name="schema">
        /// The schema.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <param name="foreignName">
        /// The foreign name.
        /// </param>
        /// <returns>
        /// The datarowview for foreign
        /// </returns>
        public DataRowView[] GetForeign(string schema, string tableName, string foreignName)
        {
            DataRowView[] row = foreignName != string.Empty
                                    ? this.dataViews[(int)DtView.ForeignByKey].FindRows(
                                        new object[] { schema, tableName, foreignName }, false)
                                    : this.GetForeign(schema, tableName);
            return row;
        }

        /// <summary>
        /// The get foreign keys.
        /// </summary>
        /// <param name="schema">
        /// The schema.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <param name="foreignName">
        /// The foreign name.
        /// </param>
        /// <returns>
        /// The datarowview for keys
        /// </returns>
        public DataRowView[] GetForeignKeys(string schema, string tableName, string foreignName)
        {
            return this.dataViews[(int)DtView.ForeignKeyByTableName].FindRows(
                new object[] { schema, tableName, foreignName }, true);
        }

        /// <summary>
        /// find check constraints
        /// </summary>
        /// <param name="schema">
        /// The schema.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <returns>
        /// The datarowview
        /// </returns>
        public DataRowView[] GetCheckConstraints(string schema, string tableName)
        {
            return this.dataViews[(int)DtView.CheckByTableName].FindRows(new object[] { schema, tableName }, true);
        }

        /// <summary>
        /// find check constraints
        /// </summary>
        /// <param name="schema">
        /// The schema.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <param name="constraintName">
        /// The contraint name
        /// </param>
        /// <returns>
        /// The datarowview
        /// </returns>
        public DataRowView[] GetCheckConstraints(string schema, string tableName, string constraintName)
        {
            DataRowView[] row = constraintName != string.Empty ? this.Check.DefaultView.FindRows(new object[] { schema, tableName, constraintName }) : this.GetCheckConstraints(schema, tableName);
            return row;
        }

        /// <summary>
        /// find indexes
        /// </summary>
        /// <param name="schema">
        /// The schema.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <returns>
        /// The datarow view
        /// </returns>
        public DataRowView[] GetIndex(string schema, string tableName)
        {
            return this.dataViews[(int)DtView.IndexByTableName].FindRows(new object[] { schema, tableName }, false);
        }

        /// <summary>
        /// find index keys
        /// </summary>
        /// <param name="schema">
        /// The schema.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <param name="indexName">
        /// The index name
        /// </param>
        /// <returns>
        /// The index key
        /// </returns>
        public DataRowView[] GetIndexKeys(string schema, string tableName, string indexName)
        {
            return this.dataViews[(int)DtView.IndexKeyByTableName].FindRows(new object[] { schema, tableName, indexName }, true);
        }

        /// <summary>
        /// find indexes
        /// </summary>
        /// <param name="schema">
        /// The schema.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <param name="indexName">
        /// The index name
        /// </param>
        /// <returns>
        /// The index key
        /// </returns>        
        public DataRowView[] GetIndex(string schema, string tableName, string indexName)
        {
            DataRowView[] row = indexName != string.Empty
                                    ? this.Index.DefaultView.FindRows(new object[] { schema, tableName, indexName })
                                    : this.GetIndex(schema, tableName);
            return row;
        }

        /// <summary>
        /// find primary key
        /// </summary>
        /// <param name="schema">
        /// The schema.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <returns>
        /// The primari key rows
        /// </returns>
        public DataRowView[] GetPrimaryKey(string schema, string tableName)
        {
            return this.dataViews[(int)DtView.PrimaryKeyByTableName].FindRows(new object[] { schema, tableName }, false);
        }

        /// <summary>
        /// find all unique keys
        /// </summary>
        /// <param name="schema">
        /// The schema.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <returns>
        /// The unique keys
        /// </returns>
        public DataRowView[] GetUniqueKey(string schema, string tableName)
        {
            return this.dataViews[(int)DtView.UniqueByTableName].FindRows(new object[] { schema, tableName }, false);
        }

        /// <summary>
        /// Get only one key
        /// </summary>
        /// <param name="schema">
        /// The schema.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <param name="indexName">
        /// The index name
        /// </param>
        /// <returns>
        /// The first Key
        /// </returns>
        public DataRowView[] GetUniqueKey(string schema, string tableName, string indexName)
        {
            var row = indexName != string.Empty ? this.Index.DefaultView.FindRows(new object[] { schema, tableName, indexName }) : this.GetUniqueKey(schema, tableName);
            return row;
        }

        /// <summary>
        /// Find Fields
        /// </summary>
        /// <param name="schema">
        /// The schema
        /// </param>
        /// <param name="tableName">
        /// The table name
        /// </param>
        /// <returns>
        /// The fields
        /// </returns>
        public DataRowView[] GetField(string schema, string tableName)
        {
            return this.dataViews[(int)DtView.FieldByTableName].FindRows(new object[] { schema, tableName }, true);
        }

        /// <summary>
        /// Find fields
        /// </summary>
        /// <param name="schema">
        /// The schema
        /// </param>
        /// <param name="tableName">
        /// The table name
        /// </param>
        /// <param name="columnName">
        /// The column name
        /// </param>
        /// <returns>
        /// The field row view
        /// </returns>
        public DataRowView[] GetField(string schema, string tableName, string columnName)
        {
            DataRowView[] row = columnName != string.Empty ? this.Fields.DefaultView.FindRows(new object[] { schema, tableName, columnName }) : this.GetField(schema, tableName);
            return row;
        }

        /// <summary>
        /// Get Sql definition (sp,view,trigger,function)
        /// </summary>
        /// <param name="schema">
        /// The schema name
        /// </param>
        /// <param name="name">
        /// The object name
        /// </param>
        /// <returns>
        /// The get sql definition.
        /// </returns>
        public string GetSqlDefinition(string schema, string name)
        {
            string s = string.Empty;
            DetailsRow dr = this.Details.FindBySchemaNameName(schema, name);
            if (dr != null)
            {
                s = dr.Text;
            }

            for (int i = 0; i < this.Details.Rows.Count; i++) 
            {
                Console.WriteLine(this.Details.Rows[i].ItemArray[1].ToString());
            }

            return s;
        }

        /// <summary>
        /// Get user row
        /// </summary>
        /// <param name="userName">
        /// The user name.
        /// </param>
        /// <returns>
        /// The user row
        /// </returns>
        public UserRow GetUser(string userName)
        {
            return this.User.FindByName(userName);
        }

        /// <summary>
        /// The init data view.
        /// </summary>
        private void InitDataView()
        {
            this.dataViews = new DataViewDs[(int)DtView.MAXIMUM];
            this.dataViews[(int)DtView.CheckByTableName] = new DataViewDs(this.Check, string.Empty, DataViewDs.KeysType.Name);
            this.dataViews[(int)DtView.CheckByKey] = new DataViewDs(this.Check, string.Empty, DataViewDs.KeysType.Primary);

            // new DataViewDs(tblCheck.DefaultView,"");
            this.dataViews[(int)DtView.AllIndexByTableName] = new DataViewDs(this.Index, string.Empty, DataViewDs.KeysType.Name);
            this.dataViews[(int)DtView.IndexByTableName] = new DataViewDs(this.dataViews[(int)DtView.AllIndexByTableName], "IsConstraint=0");
            this.dataViews[(int)DtView.PrimaryKeyByTableName] = new DataViewDs(this.dataViews[(int)DtView.AllIndexByTableName], "IsPrimaryKey = 1 AND isUnique=1 AND IsConstraint=1");
            this.dataViews[(int)DtView.UniqueByTableName] = new DataViewDs(this.dataViews[(int)DtView.AllIndexByTableName], "IsPrimaryKey = 0 AND isUnique=1 AND IsConstraint=1");
            this.dataViews[(int)DtView.FieldByTableName] = new DataViewDs(this.Fields, string.Empty, DataViewDs.KeysType.Name);
            this.dataViews[(int)DtView.FieldByKey] = new DataViewDs(this.Fields, string.Empty, DataViewDs.KeysType.Primary);
            this.dataViews[(int)DtView.AllIndexByKey] = new DataViewDs(this.Index, string.Empty, DataViewDs.KeysType.Primary);
            this.dataViews[(int)DtView.ForeignByTableName] = new DataViewDs(this.Foreign, string.Empty, DataViewDs.KeysType.Name);
            this.dataViews[(int)DtView.ForeignByKey] = new DataViewDs(this.Foreign, string.Empty, DataViewDs.KeysType.Primary);
            this.dataViews[(int)DtView.ForeignKeyByTableName] = new DataViewDs(this.ForeignKey, string.Empty, DataViewDs.KeysType.ForeignName);
            this.dataViews[(int)DtView.IndexKeyByTableName] = new DataViewDs(this.IndexKey, string.Empty, DataViewDs.KeysType.IndexName);
            this.dataViews[(int)DtView.ForeignKeyByKey] = new DataViewDs(this.ForeignKey, string.Empty, DataViewDs.KeysType.Primary);
            this.dataViews[(int)DtView.IndexKeyByKey] = new DataViewDs(this.IndexKey, string.Empty, DataViewDs.KeysType.Primary);
        }

        /// <summary>
        /// The init method
        /// </summary>
        private void Init()
        {
            this.InitDataView();
        }
    }
}